home *** CD-ROM | disk | FTP | other *** search
/ EuroCD 3 / EuroCD 3.iso / Programming / PPCbwb111 / source / bwb_cmd.c next >
C/C++ Source or Header  |  1998-06-24  |  35KB  |  1,568 lines

  1. /***************************************************************
  2.  
  3.         bwb_cmd.c       Miscellaneous Commands
  4.                         for Bywater BASIC Interpreter
  5.  
  6.                         Commands:       RUN
  7.                                         LET
  8.                                         LOAD
  9.                                         MERGE
  10.                                         CHAIN
  11.                                         NEW
  12.                                         RENUM
  13.                                         SAVE
  14.                                         LIST
  15.                                         GOTO
  16.                                         GOSUB
  17.                                         RETURN
  18.                                         ON
  19.                                         STOP
  20.                                         END
  21.                                         SYSTEM
  22.                                         TRON
  23.                                         TROFF
  24.                                         DELETE
  25.                                         RANDOMIZE
  26.                     ENVIRON
  27.                                         CMDS            (*debugging)
  28.  
  29.                         Copyright (c) 1992, Ted A. Campbell
  30.  
  31.                         Bywater Software
  32.                         P. O. Box 4023
  33.                         Duke Station
  34.                         Durham, NC  27706
  35.  
  36.                         email: tcamp@acpub.duke.edu
  37.  
  38.         Copyright and Permissions Information:
  39.  
  40.         All U.S. and international copyrights are claimed by the
  41.         author. The author grants permission to use this code
  42.         and software based on it under the following conditions:
  43.         (a) in general, the code and software based upon it may be
  44.         used by individuals and by non-profit organizations; (b) it
  45.         may also be utilized by governmental agencies in any country,
  46.         with the exception of military agencies; (c) the code and/or
  47.         software based upon it may not be sold for a profit without
  48.         an explicit and specific permission from the author, except
  49.         that a minimal fee may be charged for media on which it is
  50.         copied, and for copying and handling; (d) the code must be
  51.         distributed in the form in which it has been released by the
  52.         author; and (e) the code and software based upon it may not
  53.         be used for illegal activities.
  54.  
  55. ***************************************************************/
  56.  
  57. #include <stdio.h>
  58. #include <stdlib.h>
  59. #include <math.h>
  60. #include <string.h>
  61.  
  62. #include "bwbasic.h"
  63. #include "bwb_mes.h"
  64.  
  65. struct gsse *bwb_gss;            /* GOSUB stack */
  66. int bwb_gssc = 0;            /* GOSUB stack counter */
  67. int err_gosubn = 0;            /* line number for error GOSUB */
  68.  
  69. extern struct bwb_line *bwb_xnew( struct bwb_line *l );
  70. extern struct bwb_line *bwb_onerror( struct bwb_line *l );
  71.  
  72. /***************************************************************
  73.  
  74.         FUNCTION:       bwb_null()
  75.  
  76.         DESCRIPTION:
  77.  
  78. ***************************************************************/
  79.  
  80. struct bwb_line *
  81. bwb_null( struct bwb_line *l )
  82.    {
  83. #if  INTENSIVE_DEBUG
  84.    sprintf( bwb_ebuf, "in bwb_null(): NULL function: argc = %d", l->argc );
  85.    bwb_debug( bwb_ebuf );
  86. #endif
  87.    l->next->position = 0;
  88.    return l->next;
  89.    }
  90.  
  91. /***************************************************************
  92.  
  93.     FUNCTION:       bwb_rem()
  94.  
  95.         DESCRIPTION:
  96.  
  97. ***************************************************************/
  98.  
  99. struct bwb_line *
  100. bwb_rem( struct bwb_line *l )
  101.    {
  102. #if INTENSIVE_DEBUG
  103.    sprintf( bwb_ebuf, "in bwb_rem(): REM command" );
  104.    bwb_debug( bwb_ebuf );
  105. #endif
  106.  
  107.    l->position = strlen( l->buffer ) - 1;
  108.  
  109.    l->next->position = 0;
  110.    return l->next;
  111.    }
  112.  
  113. /***************************************************************
  114.  
  115.         FUNCTION:       bwb_run()
  116.  
  117.         DESCRIPTION:
  118.  
  119. ***************************************************************/
  120.  
  121. struct bwb_line *
  122. bwb_run( struct bwb_line *l )
  123.    {
  124.    struct bwb_line *current, *x;
  125.    int go_lnumber;                /* line number to go to */
  126.    register int n;                /* counter */
  127.    char tbuf[ MAXSTRINGSIZE + 1 ];
  128.    struct exp_ese *e;
  129.    FILE *input;
  130.  
  131. #if INTENSIVE_DEBUG
  132.    sprintf( bwb_ebuf, "in bwb_run(): entered function. buffer <%s> pos <%d>",
  133.       l->buffer, l->position );
  134.    bwb_debug( bwb_ebuf );
  135. #endif
  136.  
  137.    /* see if there is an element */
  138.  
  139.    current = NULL;
  140.    adv_ws( l->buffer, &( l->position ) );
  141. #if INTENSIVE_DEBUG
  142.    sprintf( bwb_ebuf, "in bwb_run(): check buffer <%s> pos <%d> char <0x%x>",
  143.       l->buffer, l->position, l->buffer[ l->position ] );
  144.    bwb_debug( bwb_ebuf );
  145. #endif
  146.    switch ( l->buffer[ l->position ] )
  147.       {
  148.       case '\0':
  149.       case '\n':
  150.       case '\r':
  151.       case ':':
  152. #if INTENSIVE_DEBUG
  153.          sprintf( bwb_ebuf, "in bwb_run(): no argument; begin at start.next" );
  154.          bwb_debug( bwb_ebuf );
  155. #endif
  156.          current = bwb_start.next;
  157.          e = NULL;
  158.          break;
  159.       default:
  160.          e = bwb_exp( l->buffer, FALSE, &( l->position ) );
  161.          break;
  162.       }
  163.  
  164.    /* check its type: if it is a string, open the file and execute it */
  165.  
  166.    if (( e != NULL ) && ( e->type == STRING ))
  167.       {
  168.       bwb_new( l );                /* clear memory */
  169.       str_btoc( tbuf, exp_getsval( e ) );    /* get string in tbuf */
  170.       if ( ( input = fopen( tbuf, "r" )) == NULL )    /* open file */
  171.          {
  172.          sprintf( bwb_ebuf, err_openfile, tbuf );
  173.          bwb_error( bwb_ebuf );
  174.          }
  175.       bwb_fload( input );        /* load program */
  176.       bwb_run( &bwb_start );        /* and call bwb_run() recursively */
  177.       }
  178.  
  179.    /* else if it is a line number, execute the progrm in memory
  180.       at that line number */
  181.  
  182.    else
  183.       {
  184.  
  185.       if ( current == NULL )
  186.          {
  187.  
  188.          if ( e != NULL )
  189.             {
  190.             go_lnumber = exp_getival( e );
  191.             }
  192.  
  193. #if INTENSIVE_DEBUG
  194.          sprintf( bwb_ebuf, "in bwb_run(): element detected <%s>, lnumber <%d>",
  195.             tbuf, go_lnumber );
  196.          bwb_debug( bwb_ebuf );
  197. #endif
  198.  
  199.          for ( x = bwb_start.next; x != &bwb_end; x = x->next )
  200.             {
  201.             if ( x->number == go_lnumber )
  202.                {
  203.                current = x;
  204.                }
  205.             }
  206.          }
  207.  
  208.       if ( current == NULL )
  209.          {
  210.          sprintf( bwb_ebuf, err_lnnotfound, go_lnumber );
  211.          bwb_error( bwb_ebuf );
  212.          return &bwb_end;
  213.          }
  214.  
  215. #if INTENSIVE_DEBUG
  216.       sprintf( bwb_ebuf, "in bwb_run(): ready to call do-while loop at line %d",
  217.          current->number );
  218.       bwb_debug( bwb_ebuf );
  219. #endif
  220.  
  221.       current->position = 0;
  222.  
  223.       while ( current != &bwb_end )
  224.          {
  225.          current = bwb_xline( current );
  226.          }
  227.  
  228.       }
  229.  
  230. #if INTENSIVE_DEBUG
  231.    sprintf( bwb_ebuf, "in bwb_run(): function complete." );
  232.    bwb_debug( bwb_ebuf );
  233. #endif
  234.  
  235.    return &bwb_end;
  236.  
  237.    }
  238.  
  239. /***************************************************************
  240.  
  241.         FUNCTION:       bwb_let()
  242.  
  243.         DESCRIPTION:
  244.  
  245. ***************************************************************/
  246.  
  247. struct bwb_line *
  248. bwb_let( struct bwb_line *l )
  249.    {
  250.  
  251. #if INTENSIVE_DEBUG
  252.    sprintf( bwb_ebuf, "in bwb_let(): pos <%d> line <%s>",
  253.       l->position, l->buffer );
  254.    bwb_debug( bwb_ebuf );
  255. #endif
  256.  
  257.    /* Call the expression interpreter to evaluate the assignment */
  258.  
  259.    bwb_exp( l->buffer, TRUE, &( l->position ) );
  260.  
  261.    l->next->position = 0;
  262.    return l->next;
  263.  
  264.    }
  265.  
  266. /***************************************************************
  267.  
  268.         FUNCTION:       bwb_chain()
  269.  
  270.         DESCRIPTION:    This C function implements the BASIC
  271.             CHAIN command.
  272.  
  273. ***************************************************************/
  274.  
  275. struct bwb_line *
  276. bwb_chain( struct bwb_line *l )
  277.    {
  278.    struct bwb_line *current;
  279.  
  280.    /* deallocate all variables except common ones */
  281.  
  282.    var_delcvars();
  283.  
  284.    /* remove old program from memory */
  285.  
  286.    bwb_xnew( l );
  287.  
  288.    /* call xload function to load new program in memory */
  289.  
  290.    bwb_xload( l );
  291.  
  292.    /* process other arguments */
  293.  
  294.    /*** TEMP -- WORKPOINT ***/
  295.  
  296.    /* run the newly loaded program */
  297.  
  298.    current = bwb_start.next;
  299.  
  300.    current->position = 0;
  301.  
  302.    while ( current != &bwb_end )
  303.       {
  304.       current = bwb_xline( current );
  305.       }
  306.  
  307.    /* return */
  308.  
  309.    return &bwb_end;
  310.  
  311.    }
  312.  
  313. /***************************************************************
  314.  
  315.         FUNCTION:       bwb_merge()
  316.  
  317.         DESCRIPTION:    This C function implements the BASIC
  318.             MERGE command.
  319.  
  320. ***************************************************************/
  321.  
  322. struct bwb_line *
  323. bwb_merge( struct bwb_line *l )
  324.    {
  325.  
  326.    /* call xload function to merge program in memory */
  327.  
  328.    bwb_xload( l );
  329.  
  330.    return l;
  331.  
  332.    }
  333.  
  334. /***************************************************************
  335.  
  336.         FUNCTION:       bwb_load()
  337.  
  338.         DESCRIPTION:    This C function implements the BASIC
  339.             LOAD command.
  340.  
  341. ***************************************************************/
  342.  
  343. struct bwb_line *
  344. bwb_load( struct bwb_line *l )
  345.    {
  346.  
  347.    /* clear current contents */
  348.  
  349.    bwb_new( l );
  350.  
  351.    /* call xload function to load program in memory */
  352.  
  353.    bwb_xload( l );
  354.  
  355.    return l;
  356.  
  357.    }
  358.  
  359. /***************************************************************
  360.  
  361.         FUNCTION:       bwb_xload()
  362.  
  363.         DESCRIPTION:    This C function implements the BASIC
  364.             LOAD command.
  365.  
  366. ***************************************************************/
  367.  
  368. struct bwb_line *
  369. bwb_xload( struct bwb_line *l )
  370.    {
  371.    FILE *loadfile;
  372.    char filename[ MAXARGSIZE ];
  373.  
  374.    /* Get an argument for filename */
  375.  
  376.    adv_ws( l->buffer, &( l->position ) );
  377.    switch( l->buffer[ l->position ] )
  378.       {
  379.       case '\0':
  380.       case '\n':
  381.       case '\r':
  382.       case ':':
  383.          bwb_error( err_nofn );
  384.          l->next->position = 0;
  385.          return l->next;
  386.       default:
  387.          break;
  388.       }
  389.  
  390.    bwb_const( l->buffer, filename, &( l->position ) );
  391.    if ( ( loadfile = fopen( filename, "r" )) == NULL )
  392.       {
  393.       sprintf( bwb_ebuf, err_openfile, filename );
  394.       bwb_error( bwb_ebuf );
  395.       l->next->position = 0;
  396.       return l->next;
  397.       }
  398.  
  399.    bwb_fload( loadfile );
  400.  
  401.    l->next->position = 0;
  402.    return l->next;
  403.    }
  404.  
  405. /***************************************************************
  406.  
  407.         FUNCTION:       bwb_new()
  408.  
  409.         DESCRIPTION:    This C function implements the BASIC
  410.             NEW command.
  411.  
  412. ***************************************************************/
  413.  
  414. struct bwb_line *
  415. bwb_new( struct bwb_line *l )
  416.    {
  417.  
  418.    /* clear program in memory */
  419.  
  420.    bwb_xnew( l );
  421.  
  422.    /* clear all variables */
  423.  
  424.    bwb_clear( l );
  425.  
  426.    return l->next;
  427.    }
  428.  
  429. /***************************************************************
  430.  
  431.         FUNCTION:       bwb_xnew()
  432.  
  433.         DESCRIPTION:    Clears the program in memory, but does not
  434.             deallocate all variables.
  435.  
  436. ***************************************************************/
  437.  
  438. struct bwb_line *
  439. bwb_xnew( struct bwb_line *l )
  440.    {
  441.    struct bwb_line *current, *previous;
  442.    int wait;
  443.  
  444.    wait = TRUE;
  445.    for ( current = bwb_start.next; current != &bwb_end; current = current->next )
  446.       {
  447.       if ( wait != TRUE )
  448.          {
  449.          free( previous );
  450.          }
  451.       wait = FALSE;
  452.       previous = current;
  453.       }
  454.  
  455.    bwb_start.next = &bwb_end;
  456.  
  457.    l->next->position = 0;
  458.  
  459.    return l->next;
  460.    }
  461.  
  462. /***************************************************************
  463.  
  464.         FUNCTION:       bwb_renum()
  465.  
  466.         DESCRIPTION:
  467.  
  468. ***************************************************************/
  469.  
  470. #ifdef ALLOW_RENUM
  471. struct bwb_line *
  472. bwb_renum( struct bwb_line *l )
  473.    {
  474.    struct bwb_line *current, *x;
  475.    register int c, o;
  476.    char tbuf[ MAXSTRINGSIZE + 1 ];
  477.  
  478.    /* set c to initial number */
  479.  
  480.    c = 10;
  481.  
  482.    /* set all reset flags to FALSE */
  483.  
  484.    for ( x = bwb_start.next; x != &bwb_end; x = x->next )
  485.       {
  486.       x->reset = FALSE;
  487.       }
  488.  
  489.    /* cycle through each line */
  490.  
  491.    for ( current = bwb_start.next; current != &bwb_end; current = current->next )
  492.       {
  493.       o = current->number;
  494.       current->number = c;
  495.  
  496.       /* run back through and change any GOTO statements
  497.          or GOSUB statements depending on this line */
  498.  
  499.       for ( x = bwb_start.next; x != &bwb_end; x = x->next )
  500.          {
  501.  
  502.          if ( ( x->vector == bwb_goto ) || ( x->vector == bwb_gosub ))
  503.             {
  504.             if ( atoi( x->argv[ 0 ] ) == o )
  505.                {
  506.  
  507.                if ( x->reset == FALSE )
  508.                   {
  509.  
  510. #if INTENSIVE_DEBUG
  511.                   sprintf( bwb_ebuf,
  512.                      "in bwb_renum(): renumbering line %d, new argument is %d",
  513.                      x->number, c );
  514.                   bwb_debug( bwb_ebuf );
  515. #endif
  516.  
  517.                   free( x->argv[ 0 ] );
  518.                   sprintf( tbuf, "%d", c );
  519.                   if ( ( x->argv[ 0 ] = calloc( 1, strlen( tbuf ) + 1 )) == NULL )
  520.                      {
  521.                      bwb_error( err_getmem );
  522.                      l->next->position = 0;
  523.                      return l->next;
  524.                      }
  525.                   strcpy( x->argv[ 0 ], tbuf );
  526.                   x->reset = TRUE;
  527.                   }
  528.                }
  529.             }
  530.  
  531.          }
  532.  
  533.       c += 10;
  534.       }
  535.  
  536.    l->next->position = 0;
  537.    return l->next;
  538.    }
  539. #endif
  540.  
  541. /***************************************************************
  542.  
  543.         FUNCTION:       bwb_save()
  544.  
  545.         DESCRIPTION:
  546.  
  547. ***************************************************************/
  548.  
  549. struct bwb_line *
  550. bwb_save( struct bwb_line *l )
  551.    {
  552.    FILE *outfile;
  553.    static char filename[ MAXARGSIZE ];
  554.  
  555. #if INTENSIVE_DEBUG
  556.    sprintf( bwb_ebuf, "in bwb_save(): entered function." );
  557.    bwb_debug( bwb_ebuf );
  558. #endif
  559.  
  560.    /* Get an argument for filename */
  561.  
  562.    adv_ws( l->buffer, &( l->position ) );
  563.    switch( l->buffer[ l->position ] )
  564.       {
  565.       case '\0':
  566.       case '\n':
  567.       case '\r':
  568.       case ':':
  569.          bwb_error( err_nofn );
  570.          l->next->position = 0;
  571.          return l->next;
  572.       default:
  573.          break;
  574.       }
  575.  
  576.    bwb_const( l->buffer, filename, &( l->position ) );
  577.    if ( ( outfile = fopen( filename, "w" )) == NULL )
  578.       {
  579.       sprintf( bwb_ebuf, err_openfile, filename );
  580.       bwb_error( bwb_ebuf );
  581.       l->next->position = 0;
  582.       return l->next;
  583.       }
  584.  
  585.    bwb_xlist( l, outfile );
  586.    fclose( outfile );
  587.  
  588.    l->next->position = 0;
  589.    return l->next;
  590.  
  591.    }
  592.  
  593. /***************************************************************
  594.  
  595.         FUNCTION:       bwb_list()
  596.  
  597.         DESCRIPTION:
  598.  
  599. ***************************************************************/
  600.  
  601. struct bwb_line *
  602. bwb_list( struct bwb_line *l )
  603.    {
  604.    bwb_xlist( l, stdout );
  605.    l->next->position = 0;
  606.    return l->next;
  607.    }
  608.  
  609. /***************************************************************
  610.  
  611.         FUNCTION:       bwb_xlist()
  612.  
  613.         DESCRIPTION:
  614.  
  615. ***************************************************************/
  616.  
  617. struct bwb_line *
  618. bwb_xlist( struct bwb_line *l, FILE *file )
  619.    {
  620.    struct bwb_line *start, *end, *current;
  621.    register int n;
  622.    static int s, e;
  623.    int f, r;
  624.    char tbuf[ MAXSTRINGSIZE + 1 ];
  625.  
  626.    start = bwb_start.next;
  627.    end = &bwb_end;
  628.  
  629.    r = bwb_numseq( &( l->buffer[ l->position ] ), &s, &e );
  630.  
  631.    if (( r == FALSE ) || ( s == 0 ))
  632.       {
  633.       s = bwb_start.next->number;
  634.       }
  635.  
  636.    if ( e == 0 )
  637.       {
  638.       e = s;
  639.       }
  640.  
  641.    if ( r == FALSE )
  642.       {
  643.       for ( current = bwb_start.next; current != &bwb_end; current = current->next )
  644.          {
  645.          if ( current->next == &bwb_end )
  646.             {
  647.             e = current->number;
  648.             }
  649.          }
  650.       }
  651.  
  652. #if INTENSIVE_DEBUG
  653.    sprintf( bwb_ebuf, "in bwb_list(): LBUFFER sequence is %d-%d", s, e );
  654.    bwb_debug( bwb_ebuf );
  655. #endif
  656.  
  657.    /* abort if either is MAXLINENO + 1 */
  658.  
  659.    if (( s == (MAXLINENO + 1) ) || ( e == (MAXLINENO + 1) ))
  660.       {
  661.       return l;
  662.       }
  663.  
  664.    /* Now try to find the actual lines in memory */
  665.  
  666.    f = FALSE;
  667.  
  668.    for ( current = bwb_start.next; current != &bwb_end; current = current->next )
  669.       {
  670.       if ( current != l )
  671.          {
  672.          current->position = 0;
  673.          adv_element( current->buffer, &( current->position ), tbuf );
  674.          if ( atoi( tbuf ) == s )
  675.             {
  676.             f = TRUE;
  677.         start = current;
  678.  
  679. #if INTENSIVE_DEBUG
  680.             sprintf( bwb_ebuf, "in bwb_list(): start line number is <%d>",
  681.                s );
  682.             bwb_debug( bwb_ebuf );
  683. #endif
  684.  
  685.             }
  686.          }
  687.       }
  688.  
  689.    /* check and see if a line number was found */
  690.  
  691.    if ( f == FALSE )
  692.       {
  693.       sprintf( bwb_ebuf, err_lnnotfound, s );
  694.       bwb_error( bwb_ebuf );
  695.       l->next->position = 0;
  696.       return l->next;
  697.       }
  698.  
  699.    if ( e > s )
  700.       {
  701.       for ( current = bwb_start.next; current != &bwb_end; current = current->next )
  702.          {
  703.          if ( current != l )
  704.             {
  705.             current->position = 0;
  706.             adv_element( current->buffer, &( current->position ), tbuf );
  707.             if ( atoi( tbuf ) == e )
  708.                {
  709. #if INTENSIVE_DEBUG
  710.                sprintf( bwb_ebuf, "in bwb_list(): end line number is <%d>",
  711.                   e );
  712.                bwb_debug( bwb_ebuf );
  713. #endif
  714.  
  715.                end = current->next;
  716.                }
  717.             }
  718.          }
  719.       }
  720.    else
  721.       {
  722.       end = start;
  723.       }
  724.  
  725.    /* previous should now be set to the line previous to the
  726.       first in the omission list */
  727.  
  728.    /* now go through and list appropriate lines */
  729.  
  730.    if ( start == end )
  731.       {
  732.       fprintf( file, "%s\n", start->buffer );
  733.       }
  734.    else
  735.       {
  736.       current = start;
  737.       while ( current != end )
  738.          {
  739.          fprintf( file, "%s\n", current->buffer );
  740.          current = current->next;
  741.          }
  742.       }
  743.  
  744.    l->next->position = 0;
  745.    return l->next;
  746.  
  747.    }
  748.  
  749. /***************************************************************
  750.  
  751.         FUNCTION:       bwb_goto
  752.  
  753.         DESCRIPTION:
  754.  
  755. ***************************************************************/
  756.  
  757. struct bwb_line *
  758. bwb_goto( struct bwb_line *l )
  759.    {
  760.    struct bwb_line *x;
  761.    char tbuf[ MAXSTRINGSIZE + 1 ];
  762.  
  763.    /* Check for argument */
  764.  
  765.    adv_ws( l->buffer, &( l->position ) );
  766.    switch( l->buffer[ l->position ] )
  767.       {
  768.       case '\0':
  769.       case '\n':
  770.       case '\r':
  771.       case ':':
  772.          bwb_error( err_noln );
  773.          l->next->position = 0;
  774.          return l->next;
  775.       default:
  776.          break;
  777.       }
  778.  
  779.    adv_element( l->buffer, &( l->position ), tbuf );
  780.  
  781.    for ( x = &bwb_start; x != &bwb_end; x = x->next )
  782.       {
  783.       if ( x->number == atoi( tbuf ) )
  784.          {
  785.          x->position = 0;
  786.          return x;
  787.          }
  788.       }
  789.  
  790.    sprintf( bwb_ebuf, err_lnnotfound, atoi( tbuf ) );
  791.    bwb_error( bwb_ebuf );
  792.  
  793.    l->next->position = 0;
  794.    return l->next;
  795.    }
  796.  
  797. /***************************************************************
  798.  
  799.         FUNCTION:       bwb_gosub()
  800.  
  801.     DESCRIPTION:    This function implements the BASIC GOSUB
  802.             command.
  803.  
  804. ***************************************************************/
  805.  
  806. struct bwb_line *
  807. bwb_gosub( struct bwb_line *l )
  808.    {
  809.    struct bwb_line *x, *nl;
  810.    int save_pos;
  811.    register int c;
  812.    char atbuf[ MAXSTRINGSIZE + 1 ];
  813.    char btbuf[ MAXSTRINGSIZE + 1 ];
  814.  
  815.    /* Check for argument */
  816.  
  817.    adv_ws( l->buffer, &( l->position ) );
  818.    switch( l->buffer[ l->position ] )
  819.       {
  820.       case '\0':
  821.       case '\n':
  822.       case '\r':
  823.       case ':':
  824.          sprintf( bwb_ebuf, err_noln );
  825.          bwb_error( bwb_ebuf );
  826.          l->next->position = 0;
  827.          return l->next;
  828.       default:
  829.          break;
  830.       }
  831.  
  832.    /* get the target line number in tbuf */
  833.  
  834.    adv_element( l->buffer, &( l->position ), atbuf );
  835.  
  836.    for ( x = &bwb_start; x != &bwb_end; x = x->next )
  837.       {
  838.  
  839.       if ( x != l )
  840.          {
  841.          x->position = 0;
  842.          }
  843.  
  844.       /* try to get line number in tbuf */
  845.  
  846.       adv_element( x->buffer, &( x->position ), btbuf );
  847.  
  848.       if ( is_numconst( btbuf ) == TRUE )
  849.          {
  850.          if ( atoi( btbuf ) == atoi( atbuf ) )
  851.             {
  852.         save_pos = l->position;
  853.  
  854. #if  INTENSIVE_DEBUG
  855.         sprintf( bwb_ebuf, "in bwb_gosub() at line <%d> gssc <%d>\n",
  856.                l->number, bwb_gssc );
  857.             bwb_debug( bwb_ebuf );
  858.             bwb_debug( "Press RETURN: " );
  859.             getchar();
  860. #endif
  861.  
  862.             /* increment the GOSUB stack counter */
  863.  
  864.             ++bwb_gssc;
  865.  
  866.             x->cmdnum = -1;
  867.             x->marked = FALSE;
  868.             x->position = 0;
  869.  
  870.             do
  871.                {
  872.                bwb_gss[ bwb_gssc ].position = 0;
  873.  
  874.            /* execute the line */
  875.  
  876.            nl = bwb_xline( x );
  877.  
  878.            /* check for RETURN in the line */
  879.  
  880.            if ( x->cmdnum == getcmdnum( "RETURN" ) )
  881.           {
  882.           l->position = save_pos;
  883. #if  INTENSIVE_DEBUG
  884.           sprintf( bwb_ebuf, "in bwb_gosub(): return to line <%d>, position <%d>, gssc <%d>",
  885.              l->number, l->position, bwb_gssc );
  886.           bwb_debug( bwb_ebuf );
  887. #endif
  888.           l->next->position = 0;
  889.           return l->next;     /* but why shouldn't we continue processing */
  890.           }            /* this line? */
  891.                     /* answer: bwb_xline() will continue */
  892.            x = nl;
  893.  
  894.            }
  895.  
  896.         while ( TRUE );
  897.  
  898.             }
  899.          }
  900.       }
  901.  
  902.    sprintf( bwb_ebuf, err_lnnotfound, atoi( atbuf ) );
  903.    bwb_error( bwb_ebuf );
  904.  
  905.    l->next->position = 0;
  906.    return l->next;
  907.  
  908.    }
  909.  
  910. /***************************************************************
  911.  
  912.         FUNCTION:       bwb_return()
  913.  
  914.     DESCRIPTION:    This function implements the BASIC RETURN
  915.             command.
  916.  
  917. ***************************************************************/
  918.  
  919. struct bwb_line *
  920. bwb_return( struct bwb_line *l )
  921.    {
  922.  
  923. #if  INTENSIVE_DEBUG
  924.    sprintf( bwb_ebuf, "in bwb_return() at line <%d> bwb_gssc <%d>, cmdnum <%d>",
  925.       l->number, bwb_gssc, l->cmdnum );
  926.    bwb_debug( bwb_ebuf );
  927. #endif
  928.  
  929.    if ( bwb_gssc < 1 )
  930.       {
  931. #if PROG_ERRORS
  932.       sprintf( bwb_ebuf, "in bwb_return(): bwb_gssc <%d>", bwb_gssc );
  933. #else
  934.       sprintf( bwb_ebuf, ERR_RETNOGOSUB );
  935. #endif
  936.       bwb_error( bwb_ebuf );
  937.       l->next->position = 0;
  938.       return l->next;
  939.       }
  940.  
  941.    --bwb_gssc;
  942.  
  943. #if  INTENSIVE_DEBUG
  944.    sprintf( bwb_ebuf, "in bwb_return() at line <%d>: gss level <%d>",
  945.       l->number, bwb_gssc );
  946.    bwb_debug( bwb_ebuf );
  947. #endif
  948.  
  949.    l->cmdnum = getcmdnum( "RETURN" );
  950.    l->marked = FALSE;
  951.  
  952.    l->next->position = 0;
  953.    return l->next;
  954.  
  955.    }
  956.  
  957. /***************************************************************
  958.  
  959.         FUNCTION:       bwb_on
  960.  
  961.         DESCRIPTION:    This function implements the BASIC ON...
  962.                         GOTO or ON...GOSUB statements.
  963.  
  964. ***************************************************************/
  965.  
  966. struct bwb_line *
  967. bwb_on( struct bwb_line *l )
  968.    {
  969.    struct bwb_line *x;
  970.    char varname[ MAXVARNAMESIZE + 1 ];
  971.    static int p;
  972.    struct exp_ese *rvar;
  973.    int v;
  974.    int loop;
  975.    int num_lines;
  976.    int command;
  977.    int lines[ MAX_GOLINES ];
  978.    char tbuf[ MAXSTRINGSIZE + 1 ];
  979.    char sbuf[ 7 ];
  980.  
  981.    /* Check for argument */
  982.  
  983.    adv_ws( l->buffer, &( l->position ) );
  984.  
  985.    switch( l->buffer[ l->position ] )
  986.       {
  987.       case '\0':
  988.       case '\n':
  989.       case '\r':
  990.       case ':':
  991.          sprintf( bwb_ebuf, err_incomplete );
  992.          bwb_error( bwb_ebuf );
  993.          l->next->position = 0;
  994.          return l->next;
  995.       default:
  996.          break;
  997.       }
  998.  
  999.    /* get the variable name or numerical constant */
  1000.  
  1001.    adv_element( l->buffer, &( l->position ), varname );
  1002.  
  1003.    /* check for ON ERROR statement */
  1004.  
  1005.    strncpy( sbuf, varname, 6 );
  1006.    bwb_strtoupper( sbuf );
  1007.    if ( strcmp( sbuf, "ERROR" ) == 0 )
  1008.       {
  1009. #if INTENSIVE_DEBUG
  1010.       sprintf( bwb_ebuf, "in bwb_on(): detected ON ERROR" );
  1011.       bwb_debug( bwb_ebuf );
  1012. #endif
  1013.       return bwb_onerror( l );
  1014.       }
  1015.  
  1016.    /* evaluate the variable name or constant */
  1017.  
  1018.    p = 0;
  1019.    rvar = bwb_exp( varname, FALSE, &p );
  1020.    v = exp_getival( rvar );
  1021.  
  1022. #if INTENSIVE_DEBUG
  1023.    sprintf( bwb_ebuf, "in bwb_on(): value is <%d>", v );
  1024.    bwb_debug( bwb_ebuf );
  1025. #endif
  1026.  
  1027.    /* Get GOTO or GOSUB statements */
  1028.  
  1029.    adv_element( l->buffer, &( l->position ), tbuf );
  1030.    bwb_strtoupper( tbuf );
  1031.    if ( strncmp( tbuf, "GOTO", (size_t) 4 ) == 0 )
  1032.       {
  1033.       command = getcmdnum( "GOTO" );
  1034.       }
  1035.    else if ( strncmp( tbuf, "GOSUB", (size_t) 5 ) == 0 )
  1036.       {
  1037.       command = getcmdnum( "GOSUB" );
  1038.       }
  1039.    else
  1040.       {
  1041.       sprintf( bwb_ebuf, ERR_ONNOGOTO );
  1042.       bwb_error( bwb_ebuf );
  1043.       l->next->position = 0;
  1044.       return l->next;
  1045.       }
  1046.  
  1047.    num_lines = 0;
  1048.  
  1049.    loop = TRUE;
  1050.    while( loop == TRUE )
  1051.       {
  1052.  
  1053.       /* read a line number */
  1054.  
  1055.       inp_adv( l->buffer, &( l->position ) );
  1056.       adv_element( l->buffer, &( l->position ), tbuf );
  1057.  
  1058.       lines[ num_lines ] = atoi( tbuf );
  1059.  
  1060.       ++num_lines;
  1061.  
  1062.       if ( num_lines >= MAX_GOLINES )
  1063.          {
  1064.          loop = FALSE;
  1065.          }
  1066.  
  1067.       /* check for end of line */
  1068.  
  1069.       adv_ws( l->buffer, &( l->position ) );
  1070.       switch( l->buffer[ l->position ] )
  1071.          {
  1072.          case '\0':
  1073.          case '\n':
  1074.          case '\r':
  1075.          case ':':
  1076.             loop = FALSE;
  1077.             break;
  1078.          }
  1079.  
  1080.       }
  1081.  
  1082.    /* Be sure value is in range */
  1083.  
  1084.    if ( ( v < 1 ) || ( v > num_lines ))
  1085.       {
  1086.       sprintf( bwb_ebuf, err_valoorange );
  1087.       bwb_error( bwb_ebuf );
  1088.       l->next->position = 0;
  1089.       return l->next;
  1090.       }
  1091.  
  1092.    if ( command == getcmdnum( "GOTO" ))
  1093.       {
  1094.       sprintf( tbuf, "GOTO %d", lines[ v - 1 ] );
  1095.       return cnd_xpline( l, tbuf );
  1096.       }
  1097.    else if ( command == getcmdnum( "GOSUB" ))
  1098.       {
  1099.       sprintf( tbuf, "GOSUB %d", lines[ v - 1 ] );
  1100.       return cnd_xpline( l, tbuf );
  1101.       }
  1102.    else
  1103.       {
  1104. #if PROG_ERRORS
  1105.       sprintf( bwb_ebuf, "in bwb_on(): invalid value for command." );
  1106.       bwb_error( bwb_ebuf );
  1107. #else
  1108.       bwb_error( err_syntax );
  1109. #endif
  1110.       l->next->position = 0;
  1111.       return l->next;
  1112.       }
  1113.  
  1114.    }
  1115.  
  1116. /***************************************************************
  1117.  
  1118.         FUNCTION:       bwb_onerror()
  1119.  
  1120.         DESCRIPTION:    This C function implements the BASIC
  1121.                 ON ERROR GOSUB command.
  1122.  
  1123. ***************************************************************/
  1124.  
  1125. struct bwb_line *
  1126. bwb_onerror( struct bwb_line *l )
  1127.    {
  1128.    char tbuf[ MAXSTRINGSIZE + 1 ];
  1129.  
  1130. #if INTENSIVE_DEBUG
  1131.    sprintf( bwb_ebuf, "in bwb_onerror(): entered function" );
  1132.    bwb_debug( bwb_ebuf );
  1133. #endif
  1134.  
  1135.    /* get the GOSUB STATEMENT */
  1136.  
  1137.    adv_element( l->buffer, &( l->position ), tbuf );
  1138.  
  1139.    /* check for GOSUB statement */
  1140.  
  1141.    bwb_strtoupper( tbuf );
  1142.    if ( strcmp( tbuf, "GOSUB" ) != 0 )
  1143.       {
  1144. #if PROG_ERRORS
  1145.       sprintf( bwb_ebuf, "in bwb_onerror(): GOSUB statement missing" );
  1146.       bwb_error( bwb_ebuf );
  1147. #else
  1148.       bwb_error( err_syntax );
  1149. #endif
  1150.       return l;
  1151.       }
  1152.  
  1153.    /* get the GOSUB line number */
  1154.  
  1155.    adv_element( l->buffer, &( l->position ), tbuf );
  1156.    err_gosubn = atoi( tbuf );
  1157.  
  1158.    return l;
  1159.    }
  1160.  
  1161. /***************************************************************
  1162.  
  1163.         FUNCTION:       bwb_stop()
  1164.  
  1165.         DESCRIPTION:
  1166.  
  1167. ***************************************************************/
  1168.  
  1169. struct bwb_line *
  1170. bwb_stop( struct bwb_line *l )
  1171.    {
  1172.    return bwb_xend( l );
  1173.    }
  1174.  
  1175. /***************************************************************
  1176.  
  1177.         FUNCTION:       bwb_xend()
  1178.  
  1179.         DESCRIPTION:
  1180.  
  1181. ***************************************************************/
  1182.  
  1183. struct bwb_line *
  1184. bwb_xend( struct bwb_line *l )
  1185.    {
  1186.  
  1187. #if INTENSIVE_DEBUG
  1188.    sprintf( bwb_ebuf, "in bwb_xend(): entered funtion" );
  1189.    bwb_debug( bwb_ebuf );
  1190. #endif
  1191.  
  1192.    break_handler();
  1193.  
  1194.    return &bwb_end;
  1195.    }
  1196.  
  1197. /***************************************************************
  1198.  
  1199.         FUNCTION:       bwb_system()
  1200.  
  1201.         DESCRIPTION:
  1202.  
  1203.  
  1204. ***************************************************************/
  1205.  
  1206. struct bwb_line *
  1207. bwb_system( struct bwb_line *l )
  1208.    {
  1209.    fprintf( stdout, "\n" );
  1210.  
  1211. #if INTENSIVE_DEBUG
  1212.    bwb_debug( "in bwb_system(): ready to exit" );
  1213. #endif
  1214.  
  1215.    exit( 0 );
  1216.    return &bwb_end;                 /* to make LINT happy */
  1217.    }
  1218.  
  1219. /***************************************************************
  1220.  
  1221.         FUNCTION:       bwb_tron()
  1222.  
  1223.         DESCRIPTION:
  1224.  
  1225. ***************************************************************/
  1226.  
  1227. struct bwb_line *
  1228. bwb_tron( struct bwb_line *l )
  1229.    {
  1230.    bwb_trace = TRUE;
  1231.    fprintf( stdout, "Trace is ON\n" );
  1232.    l->next->position = 0;
  1233.    return l->next;
  1234.    }
  1235.  
  1236. /***************************************************************
  1237.  
  1238.         FUNCTION:       bwb_troff()
  1239.  
  1240.         DESCRIPTION:
  1241.  
  1242. ***************************************************************/
  1243.  
  1244. struct bwb_line *
  1245. bwb_troff( struct bwb_line *l )
  1246.    {
  1247.    bwb_trace = FALSE;
  1248.    fprintf( stdout, "Trace is OFF\n" );
  1249.    l->next->position = 0;
  1250.    return l->next;
  1251.    }
  1252.  
  1253. /***************************************************************
  1254.  
  1255.  
  1256.         FUNCTION:       bwb_delete()
  1257.  
  1258.         DESCRIPTION:
  1259.  
  1260. ***************************************************************/
  1261.  
  1262. struct bwb_line *
  1263.  
  1264. bwb_delete( struct bwb_line *l )
  1265.    {
  1266.    struct bwb_line *start, *end, *current, *previous, *p;
  1267.    register int n;
  1268.    static int s, e;
  1269.    int f;
  1270.    char tbuf[ MAXSTRINGSIZE + 1 ];
  1271.  
  1272.    previous = &bwb_start;
  1273.    start = bwb_start.next;
  1274.    end = &bwb_end;
  1275.  
  1276.    bwb_numseq( &( l->buffer[ l->position ] ), &s, &e );
  1277.  
  1278. #if INTENSIVE_DEBUG
  1279.    sprintf( bwb_ebuf, "in bwb_delete(): LBUFFER sequence is %d-%d", s, e );
  1280.    bwb_debug( bwb_ebuf );
  1281. #endif
  1282.  
  1283.    /* Now try to find the actual lines in memory */
  1284.  
  1285.    previous = p = &bwb_start;
  1286.    f = FALSE;
  1287.  
  1288.    for ( current = bwb_start.next; current != &bwb_end; current = current->next )
  1289.       {
  1290.       if ( current != l )
  1291.          {
  1292.          current->position = 0;
  1293.          adv_element( current->buffer, &( current->position ), tbuf );
  1294.          if ( atoi( tbuf ) == s )
  1295.             {
  1296.             f = TRUE;
  1297.             previous = p;
  1298.             start = current;
  1299.  
  1300. #if INTENSIVE_DEBUG
  1301.             sprintf( bwb_ebuf, "in bwb_delete(): start line number is <%d>",
  1302.                s );
  1303.             bwb_debug( bwb_ebuf );
  1304. #endif
  1305.  
  1306.             }
  1307.          }
  1308.       p = current;
  1309.       }
  1310.  
  1311.    /* check and see if a line number was found */
  1312.  
  1313.    if ( f == FALSE )
  1314.       {
  1315.       sprintf( bwb_ebuf, err_lnnotfound, s );
  1316.       bwb_error( bwb_ebuf );
  1317.       l->next->position = 0;
  1318.       return l->next;
  1319.       }
  1320.  
  1321.    if ( e > s )
  1322.       {
  1323.       for ( current = bwb_start.next; current != &bwb_end; current = current->next )
  1324.          {
  1325.          if ( current != l )
  1326.             {
  1327.             current->position = 0;
  1328.             adv_element( current->buffer, &( current->position ), tbuf );
  1329.             if ( atoi( tbuf ) == e )
  1330.                {
  1331. #if INTENSIVE_DEBUG
  1332.                sprintf( bwb_ebuf, "in bwb_delete(): end line number is <%d>",
  1333.                   e );
  1334.                bwb_debug( bwb_ebuf );
  1335. #endif
  1336.  
  1337.                end = current->next;
  1338.                }
  1339.             }
  1340.          }
  1341.       }
  1342.    else
  1343.       {
  1344.       end = start;
  1345.       }
  1346.  
  1347.    /* previous should now be set to the line previous to the
  1348.       first in the omission list */
  1349.  
  1350.    /* now go through and delete appropriate lines */
  1351.  
  1352.    current = start;
  1353.    while ( current != end )
  1354.       {
  1355.  
  1356. #if INTENSIVE_DEBUG
  1357.       sprintf( bwb_ebuf, "in bwb_delete(): deleting line %d",
  1358.          current->number );
  1359.       bwb_debug( bwb_ebuf );
  1360. #endif
  1361.  
  1362.       /* free line memory */
  1363.  
  1364.       bwb_freeline( current );
  1365.  
  1366.       /* recycle */
  1367.  
  1368.       current = current->next;
  1369.       }
  1370.  
  1371.    /* reset link */
  1372.  
  1373.    previous->next = current;
  1374.  
  1375.    l->next->position = 0;
  1376.    return l->next;
  1377.    }
  1378.  
  1379. /***************************************************************
  1380.  
  1381.         FUNCTION:       bwb_randomize()
  1382.  
  1383.         DESCRIPTION:
  1384.  
  1385. ***************************************************************/
  1386.  
  1387. struct bwb_line *
  1388. bwb_randomize( struct bwb_line *l )
  1389.    {
  1390.    register unsigned n;
  1391.    char tbuf[ MAXSTRINGSIZE + 1 ];
  1392.  
  1393.    /* Check for argument */
  1394.  
  1395.    adv_ws( l->buffer, &( l->position ) );
  1396.    switch( l->buffer[ l->position ] )
  1397.       {
  1398.       case '\0':
  1399.       case '\n':
  1400.       case '\r':
  1401.       case ':':
  1402.          n = (unsigned) 1;
  1403.          break;
  1404.       default:
  1405.          n = (unsigned) 0;
  1406.          break;
  1407.       }
  1408.  
  1409.    /* get the argument in tbuf */
  1410.  
  1411.    if ( n == (unsigned) 0 )
  1412.       {
  1413.       adv_element( l->buffer, &( l->position ), tbuf );
  1414.       n = (unsigned) atoi( tbuf );
  1415.       }
  1416.  
  1417. #if INTENSIVE_DEBUG
  1418.    sprintf( bwb_ebuf, "in bwb_randomize(): argument is <%d>", n );
  1419.    bwb_debug( bwb_ebuf );
  1420. #endif
  1421.  
  1422.    srand( n );
  1423.  
  1424.    l->next->position = 0;
  1425.    return l->next;
  1426.    }
  1427.  
  1428.  
  1429. /***************************************************************
  1430.  
  1431.         FUNCTION:       bwb_environ()
  1432.  
  1433.         DESCRIPTION:    This C function implements the BASIC
  1434.             ENVIRON command.  
  1435.  
  1436. ***************************************************************/
  1437.  
  1438. #if UNIX_CMDS
  1439. struct bwb_line *
  1440. bwb_environ( struct bwb_line *l )
  1441.    {
  1442.    static char tbuf[ MAXSTRINGSIZE + 1 ];
  1443.    char tmp[ MAXSTRINGSIZE + 1 ];
  1444.    register int h, i;
  1445.    int pos;
  1446.    struct exp_ese *e;
  1447.  
  1448.    /* find the equals sign */
  1449.  
  1450.    for ( i = 0; ( l->buffer[ l->position ] != '=' ) && ( l->buffer[ l->position ] != '\0' ); ++i )
  1451.       {
  1452.       tbuf[ i ] = l->buffer[ l->position ];
  1453.       tbuf[ i + 1 ] = '\0';
  1454.       ++( l->position );
  1455.       }
  1456.  
  1457. #if INTENSIVE_DEBUG
  1458.    sprintf( bwb_ebuf, "in bwb_environ(): variable string is <%s>", tbuf );
  1459.    bwb_debug( bwb_ebuf );
  1460. #endif
  1461.  
  1462.    /* get the value string to be assigned */
  1463.  
  1464.    pos = 0;
  1465.    e = bwb_exp( tbuf, FALSE, &pos );
  1466.    str_btoc( tbuf, exp_getsval( e ) );
  1467.  
  1468. #if INTENSIVE_DEBUG
  1469.    sprintf( bwb_ebuf, "in bwb_environ(): variable string resolves to <%s>", tbuf );
  1470.    bwb_debug( bwb_ebuf );
  1471. #endif
  1472.  
  1473.    /* find the equals sign */
  1474.  
  1475.    adv_ws( l->buffer, &( l->position ) );
  1476.    if ( l->buffer[ l->position ] != '=' )
  1477.       {
  1478. #if PROG_ERRORS
  1479.       sprintf( bwb_ebuf, "in bwb_environ(): failed to find equal sign" );
  1480.       bwb_error( bwb_ebuf );
  1481. #else
  1482.       bwb_error( err_syntax );
  1483. #endif
  1484.       return l;
  1485.       }
  1486.    ++( l->position );
  1487.  
  1488.    /* get the value string to be assigned */
  1489.  
  1490.    e = bwb_exp( l->buffer, FALSE, &( l->position ));
  1491.    str_btoc( tmp, exp_getsval( e ) );
  1492.  
  1493. #if INTENSIVE_DEBUG
  1494.    sprintf( bwb_ebuf, "in bwb_environ(): value string resolves to <%s>", tmp );
  1495.    bwb_debug( bwb_ebuf );
  1496. #endif
  1497.  
  1498.    /* construct string */
  1499.  
  1500.    strcat( tbuf, "=" );
  1501.    strcat( tbuf, tmp );
  1502.  
  1503. #if INTENSIVE_DEBUG
  1504.    sprintf( bwb_ebuf, "in bwb_environ(): assignment string is <%s>", tbuf );
  1505.    bwb_debug( bwb_ebuf );
  1506. #endif
  1507.  
  1508.    /* now assign value to variable */
  1509.  
  1510.    if ( putenv( tbuf ) == -1 )
  1511.       {
  1512.       bwb_error( err_opsys );
  1513.       return l;
  1514.       }
  1515.  
  1516.    /* return */ 
  1517.  
  1518.    return l;
  1519.  
  1520.    }
  1521.  
  1522. #endif                    /* UNIX_CMDS */
  1523.  
  1524. /***************************************************************
  1525.  
  1526.         FUNCTION:       bwb_cmds()
  1527.  
  1528.         DESCRIPTION:
  1529.  
  1530. ***************************************************************/
  1531.  
  1532. #if PERMANENT_DEBUG
  1533. struct bwb_line *
  1534. bwb_cmds( struct bwb_line *l )
  1535.    {
  1536.    register int n;
  1537.  
  1538.    fprintf( stdout, "BWBASIC COMMANDS AVAILABLE: \n" );
  1539.  
  1540.    /* run through the command table and print comand names */
  1541.  
  1542.    for ( n = 0; n < COMMANDS; ++n )
  1543.       {
  1544.       fprintf( stdout, "%s \n", bwb_cmdtable[ n ].name );
  1545.       }
  1546.  
  1547.    l->next->position = 0;
  1548.    return l->next;
  1549.    }
  1550. #endif
  1551.  
  1552. int
  1553. getcmdnum( char *cmdstr )
  1554.    {
  1555.    register int c;
  1556.  
  1557.    for ( c = 0; c < COMMANDS; ++c )
  1558.       {
  1559.       if ( strcmp( bwb_cmdtable[ c ].name, cmdstr ) == 0 )
  1560.          {
  1561.          return c;
  1562.          }
  1563.       }
  1564.  
  1565.    return -1;
  1566.  
  1567.    }
  1568.